﻿using Sgr.UPMS.Domain.Tokens;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Sgr.Security.Tokens.Services
{
    /// <summary>
    /// UPMS临时令牌服务实现
    /// </summary>
    public class UpmsTemporaryTokenService : ITemporaryTokenService
    {
        private readonly ITemporaryTokenManager _temporaryTokenManager;
        private readonly ITemporaryTokenRepository _temporaryTokenRepository;

        public UpmsTemporaryTokenService(
            ITemporaryTokenManager temporaryTokenManager,
            ITemporaryTokenRepository temporaryTokenRepository)
        {
            _temporaryTokenManager = temporaryTokenManager;
            _temporaryTokenRepository = temporaryTokenRepository;
        }

        /// <summary>
        /// 创建一个新的临时令牌
        /// </summary>
        /// <param name="tokenType">令牌类型</param>
        /// <param name="expirationMinutes">过期时间(分钟)</param>
        /// <param name="content">令牌内容</param>
        /// <param name="deviceFingerprint">关联的设备指纹</param>
        /// <param name="userId">关联的用户标识</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns></returns>
        public async Task<TemporaryToken> CreateAsync(
            int tokenType,
            int expirationMinutes = 5,
            string? content = null,
            string? deviceFingerprint = null,
            string? userId = null,
            CancellationToken cancellationToken = default)
        {
            // 生成令牌编码
            var code = Guid.NewGuid().ToString("N");

            // 计算过期时间
            var expirationTime = DateTime.UtcNow.AddMinutes(expirationMinutes);

            // 通过领域服务创建令牌
            var token = await _temporaryTokenManager.CreateAsync(
                code,
                tokenType,
                expirationTime,
                content,
                deviceFingerprint,
                userId,
                cancellationToken);

            // 保存到仓储
            await _temporaryTokenRepository.InsertAsync(token, cancellationToken);

            // 返回令牌信息
            return new TemporaryToken
            {
                Code = token.Code,
                ExpirationTime = token.ExpirationTime
            };
        }

        /// <summary>
        /// 验证临时令牌
        /// </summary>
        /// <param name="code">令牌编码</param>
        /// <param name="tokenType">令牌类型</param>
        /// <param name="content">令牌内容</param>
        /// <param name="deviceFingerprint">关联的设备指纹</param>
        /// <param name="userId">关联的用户标识</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns></returns>
        public async Task<bool> ValidateAsync(
            string code,
            int tokenType,
            string? content = null,
            string? deviceFingerprint = null,
            string? userId = null,
            CancellationToken cancellationToken = default)
        {
            // 参数校验
            if (string.IsNullOrWhiteSpace(code))
                return false;

            // 根据编码获取令牌
            var token = await _temporaryTokenRepository.GetByCodeAsync(code, cancellationToken);
            if (token == null)
                return false;

            // 验证令牌
            var isValid = token.IsValid(tokenType, content, deviceFingerprint, userId);

            // 标记令牌为已使用并保存更新
            token.MarkAsUsed();
            await _temporaryTokenRepository.UpdateAsync(token, cancellationToken);

            return isValid;
        }
    }
}